﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CSScriptLibrary;

namespace DevelopTool.Common
{

    public static class CSScriptHelper
    {
        static List<string> localNamespaceList = AssemblyHelper.GetLocalNamespace();


        /// <summary>
        /// 执行代码
        /// </summary>
        /// <param name="mainCode">入口代码</param>
        /// <param name="customCode">自定义代码</param>
        /// <param name="libraryReferences">引用的程序集路径集合</param>
        /// <returns></returns>
        public static Tuple<bool, dynamic> ExecuteCode(string mainCode, string customCode, List<string> libraryReferences)
        {
            try
            {

                string codeStr;//需要执行的代码
                string defaultClassCode = "public class Program{\n@Method@\n}";//默认入口类
                string defaultMethodCode;
                if (mainCode.Contains("return"))
                {
                    defaultMethodCode = "public dynamic Main(){\n@Code@\n}";//默认入口方法
                }
                else
                {
                    defaultMethodCode = "public void Main(){\n@Code@\n}";//默认入口方法
                }


                if (!string.IsNullOrWhiteSpace(customCode))
                {
                    if (customCode.Contains("class"))
                    {
                        defaultMethodCode = defaultMethodCode.Replace("@Code@", mainCode);
                        defaultClassCode = defaultClassCode.Replace("@Method@", defaultMethodCode);
                        codeStr = defaultClassCode + customCode;
                    }
                    else
                    {
                        defaultMethodCode = defaultMethodCode.Replace("@Code@", mainCode);
                        defaultMethodCode = defaultMethodCode + customCode;
                        codeStr = defaultClassCode.Replace("@Method@", defaultMethodCode);
                    }
                }
                else
                {
                    defaultMethodCode = defaultMethodCode.Replace("@Code@", mainCode);
                    codeStr = defaultClassCode.Replace("@Method@", defaultMethodCode);
                }


                var eval = CSScript.CodeDomEvaluator;

                List<string> namespaceList = localNamespaceList;

                #region 设置引用的程序集命名空间
                foreach (string libraryReference in libraryReferences)
                {
                    if (!File.Exists(libraryReference))
                    {
                        return new Tuple<bool, dynamic>(false, $"未找到程序集【{libraryReference}】请检查是否存在该路径");
                    }

                    eval.ReferenceAssembly(libraryReference);
                    namespaceList.AddRange(AssemblyHelper.GetNamespaceByDll(libraryReference));
                }

                #endregion

                string namespaceStr = string.Join("", namespaceList.Distinct().Select(it => "using " + it + ";"));//拼接所有命名空间

                string aa = namespaceStr + codeStr;

                dynamic script = eval.LoadCode(namespaceStr + codeStr);

                if (mainCode.Contains("return"))//有返回值，判断代码里是否有return关键字
                {
                    dynamic result = script.Main();
                    return new Tuple<bool, dynamic>(true, result);
                }
                else//无返回值
                {
                    script.Main();
                    return new Tuple<bool, dynamic>(true, "执行成功");
                }

            }
            catch (Exception ex)
            {
                return new Tuple<bool, dynamic>(false, ex.Message);
            }
        }
    }
}
